using System;
using System.Collections.Generic;
using System.Text;
using ACS.Compiler.Parser;
using ACS.Compiler.Tables;
using ACS.Compiler.Tables.Modes;
using ACS.Compiler.Util;

namespace ACS.Compiler.Tree.Impl
{
    public class Proc : TreeBase
    {
        private string _name;
        private TypeDeclarer _declarer;
        private List<FormalParameter> _parameters = new List<FormalParameter>();
        private List<DataField> _dataFields = new List<DataField>();
        private Data _localDatal;
        private Block _code;
        private Procedure _procedure;

        DataTable _dataTable = new DataTable();
        List<DataField> _paramsMode = new List<DataField>();

        public List<DataField> DataFields
        {
            get { return _dataFields; }
        }

        public override void AllFieldsParsed()
        {
            Mode retMode = ModesTable.Instance.FindMode(_declarer);
            Procedure proc = new Procedure(
                _name, 
                FileParser.CurrentFileParser.ModuleName,
                _dataTable,
                _paramsMode,
                retMode,
                _code,
                false
                );
            _procedure = proc;
            ProcTable.Instance.AddProc(proc);
            DataTable.ExitProc();
        }

        public Procedure Procedure
        {
            get { return _procedure; }
        }

        public override void MatchBlock(Block block)
        {
            _code = block;
        }

        public override void MatchIdent(Ident ident)
        {
            DataTable.EnterProc(_dataTable);
            _name = ident.ToString();
        }

        public override void MatchData(Data data)
        {
            _localDatal = data;
            foreach (TypeField field in data.Fields)
            {
                _dataFields.Add(_dataTable.AddData(field.Declarer, field.FieldName, null));
            }
        }

        public override void MatchFormalParameter(FormalParameter parameter)
        {
            _parameters.Add(parameter);
            Mode mode = ModesTable.Instance.FindMode(parameter.Type);
            _paramsMode.Add(new DataField(null, parameter.Name, mode));
            _dataTable.AddData(parameter.Type, parameter.Name, null);
        }

        public override void MatchTypeDeclarer(TypeDeclarer declarer)
        {
            _declarer = declarer;
        }

        public string Name
        {
            get { return _name; }
        }

        public TypeDeclarer Declarer
        {
            get { return _declarer; }
        }

        public List<FormalParameter> Parameters
        {
            get { return _parameters; }
        }

        public override TreeTags Tag
        {
            get { return TreeTags.Proc; }
        }

        public Data LocalDatal
        {
            get { return _localDatal; }
        }


        public Block Code
        {
            get { return _code; }
        }
    }
}
